#ifndef __r8Bit_TILES_H__
#define __r8Bit_TILES_H__
#include <SDL/SDL.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct R8B_Surface_Tiles {
  SDL_Surface *original;
  int num_tiles;
  int width;
  int height;
  SDL_Rect *rects;
} R8B_Surface_Tiles;

  struct R8B_Tiled_Screen; //!< forward declaration

  /*! \brief Function pointer for generic functions for tiled screens. */
  typedef int (*R8B_Generic_Tiled_Screen_Function)(struct R8B_Tiled_Screen *);

  /*\brief Structure (generic) for additional functions used in the tiled screen.
   */
  typedef struct R8B_Tiled_Screen_Additional_Functionality {
    int (*onBlit)(struct R8B_Tiled_Screen *, SDL_Surface *dst, SDL_Rect *dstrect);
    R8B_Generic_Tiled_Screen_Function onFree;
    union {
      Uint32 U32;
      int i;
      long l;
      char str[16];
      char c;
      short s;
      float f;
      double d;
      struct {
	int i1;
	int i2;
      };
      uint64_t u64;
    } data[4];
  } R8B_Tiled_Screen_Additional_Functionality;
  //int R8B_Tiled_Screen_CursorFuction(struct R8B_Tiled_Screen *);

typedef struct R8B_Tiled_Screen {
  int width; //!< Number of tiles in X direction
  int height; //!< Number of tiles in Y direction	
  int crsr_x; //!< tile cursor x position
  int crsr_y; //!< tile cursor y position
  R8B_Tiled_Screen_Additional_Functionality *draw_cursor_fptr; //!< function pointer for drawing the cursor, NULL if no cursor
  int *array; //!< array which contains the tile numbers, row major
  int default_fill; //!< what tile to use if the screen is "cleared" 
  R8B_Surface_Tiles *tiles; //!< pointer to the rectangles
  short array_owned; //!< is the array owned by me? 1=I need to free this array, 0=not my business
  short tiles_owned; //!< are the tiles owned by me? 1=I need to free the surface tile, 0=not my business
  Uint32 ticks_on_creation; //!< This is the time this screen was created!
} R8B_Tiled_Screen;

/*! \brief Data type for character conversion function.
 *
 * This data type is needed as the tiles are stored as integers but we
 * would like to easily print characters. For this we need a
 * conversion function.
 */
typedef int R8B_CharConversionFun(char);


R8B_Surface_Tiles *r8b_createSurfaceTiles(SDL_Surface *src, int w, int h);
void r8b_freeSurfaceTiles(R8B_Surface_Tiles *s);

int r8b_blitTile(R8B_Surface_Tiles *st, int num, SDL_Surface *dst, SDL_Rect *dstrect);
int r8b_blitTileXY(R8B_Surface_Tiles *st, int num, SDL_Surface *dst, int x, int y);

  /*! \brief add a cursor to the tiled screen
   *
   * \param screen tiled screen to add cursor to
   * \param colour colour of the cursor
   * \param freq frequency divisor, if =0 then no blinking
   * \return 0 OK, -1 failed
   */
int r8b_addCursorTiledScreen(R8B_Tiled_Screen *screen, Uint32 colour, short freq);
R8B_Tiled_Screen *r8b_createTiledScreen(int width, int height, int default_fill, R8B_Surface_Tiles *tiles);
R8B_Tiled_Screen *r8b_createTiledScreen_with_array(int width, int height, int default_fill, R8B_Surface_Tiles *tiles, int *extern_array);
R8B_Tiled_Screen *r8b_createTiledScreen_using_surface(int width, int height, int default_fill, SDL_Surface *surf, int tile_width, int tile_height);
void r8b_freeTiledScreen(R8B_Tiled_Screen *screen);

int r8b_blitScreen(R8B_Tiled_Screen *src, SDL_Surface *dst, SDL_Rect *dstrect);
int r8b_blitScreenPart(R8B_Tiled_Screen *src, SDL_Rect *scrprt, SDL_Surface *dst, SDL_Rect *dstrect);
int r8b_blitScreenXY(R8B_Tiled_Screen *src, SDL_Surface *dst, int x, int y);
void r8b_clearScreen(R8B_Tiled_Screen *dst);
/*! Character to tile number conversion function.
 *
 * This function can be used to convert a single character in ascii to
 * the tile number. The tile number is then adjusted to correspond the
 * c64 format that is used in the CHARGEN file.
 *
 * \param c character to converse
 * \return tile number as int
 */
int r8b_c64CharConversionFun(char ch);
/*! Character to tile number conversion function.
 *
 * This function can be used to convert a single character in ascii to
 * the tile number. No further conversion is done! Actually the char
 * is first converted to a (unsigned char).
 *
 * \param c character to converse
 * \return tile number as int
 */
int r8b_defaultCharConversionFun(char c);
void r8b_fillScreen(R8B_Tiled_Screen *dst, int c);
int r8b_peekScreen(R8B_Tiled_Screen *dst, int x, int y);
void r8b_pokeScreen(R8B_Tiled_Screen *dst, int x, int y, int c);
/*! \brief "Print" tiles to the screen.
 *
 * Given a list of tile numbers these are printed (a "character" each)
 * onto the tiled screen. Wrapping and scrolling is applied as needed.
 *
 * \param scr Tiled screen pointer
 * \param tilenums Pointer to tile numbers, ended with -1
 */
void r8b_printScreen(R8B_Tiled_Screen *scr, int *tilenums);
/*! \brief Print text to the screen.
 *
 * Given a text string the characters undergo a conversion to ints by
 * the supplied function and these are printed onto the tiled
 * screen. Wrapping and scrolling is applied as needed.
 *
 * \param scr Tiled screen pointer
 * \param tilenums Pointer to tile numbers, ended with -1
 */
void r8b_printStringScreen(R8B_Tiled_Screen *scr, R8B_CharConversionFun *fun, const char *txt);
/*! \brief Print text to the screen.
 *
 * Given a text string the characters undergo a conversion to ints by
 * the supplied function and these are printed onto the tiled
 * screen. Wrapping and scrolling is applied as needed.
 *
 * After the printing a CR/LF pair is append so that the cursor is in
 * the beginning of line in the next line.
 *
 * \param scr Tiled screen pointer
 * \param tilenums Pointer to tile numbers, ended with -1
 */
void r8b_printStringScreenLn(R8B_Tiled_Screen *scr, R8B_CharConversionFun *fun, const char *txt);
/*! \brief Put a character to screen.
 *
 * The cursor is moved also.
 *
 * \param scr the tiled screen to draw on
 * \param c the "character" or tile number */
void r8b_putCharScreen(R8B_Tiled_Screen *scr, int c);
void r8b_scrollScreenUp(R8B_Tiled_Screen *dst);

#ifdef __cplusplus
}
#endif
#endif
